package personal.leil.learning.lombard;

import java.util.Comparator;
import java.util.HashSet;
import java.util.PriorityQueue;

/**
 * 输入
 * <pre>
 * <code>
 *     Project {
 *         int cost;
 *         int profit;
 *     }
 * </code>
 * </pre>
 * 正数k<br/>
 * 正数m<br/>
 * 含义:<br/>
 * costs表示项目的花费<br/>
 * profit表示项目在扣除花费之后还能挣到的钱(利润)<br/>
 * k表示你只能串行的最多做k个项目<br/>
 * m表示你初始的资金<br/>
 * 说明:<br/>
 * 你每做完一个项目，马上获得的收益，可以支持你去做下一个项目<br/>
 * 输出:<br/>
 * 你最后获得的最大钱数<br/>
 * @author Leil
 * @version 1.0
 * @since 2024/1/26
 */
public class LombardQuestion {


    public static int process(Project[] projects, int k, int m) {
        HashSet<Project> alreadyProcessed = new HashSet<>();
        return process(projects, k, m, alreadyProcessed);
    }

    public static int process(Project[] projects, int k, int m, HashSet<Project> alreadyProcessed) {
        /*
         * 根据花费由低到高排序
         */
        PriorityQueue<Project> costLessQueue = new PriorityQueue<>(Comparator.comparingInt(o -> o.cost));
        for (Project project : projects) {
            if (!alreadyProcessed.contains(project) && project.cost <= m) {
                costLessQueue.offer(project);
            }
        }
        if (costLessQueue.isEmpty()) {
            return m;
        }
        /*
         * 根据收益从高到低排序
         */
        PriorityQueue<Project> profitMoreQueue = new PriorityQueue<>((o1, o2) -> o2.profit - o1.profit);
        while (!costLessQueue.isEmpty()) {
            profitMoreQueue.offer(costLessQueue.poll());
        }
        // 并行时当前剩余的资金
        int last = m;
        // 同时并行的项目数量
        int parallel = 0;
        System.out.println("============================");
        System.out.println("当前所持有资金：" + m);
        while (!profitMoreQueue.isEmpty() && ++parallel <= k) {
            Project p = profitMoreQueue.poll();
            if (last >= p.cost) {
                m = m - p.cost + p.profit;
                last = last - p.cost;
                alreadyProcessed.add(p);
                System.out.println(p);
            }
        }
        System.out.println("=============================");

        if (parallel != 0) {
            return process(projects, k, m, alreadyProcessed);
        }
        return m;
    }



    public static class Project {
        public int cost;
        public int profit;

        public Project(int cost, int profit) {
            this.cost = cost;
            this.profit = profit;
        }

        @Override
        public String toString() {
            return String.format("Project{ cost=%d, profit=%d}", this.cost, this.profit);
        }
    }


    /********************* For Test ****************************/
    public static void main(String[] args) {
        Project[] projects = new Project[] {
                new Project(100, 200),
                new Project(100, 400),
                new Project(300, 600),
                new Project(900, 1500)
        };
//        Project[] projects = new Project[] {
//                new Project(100, 200)
//        };

        int profit = process(projects, 2, 200);
        System.out.println("最终受益：" + profit);
    }

}
